#pragma once

#include "../comm/Util.hpp"
#include "../comm/Log.hpp"


namespace ns_compile
{
    using namespace ns_util;
    using namespace ns_log;
    class compile
    {

    private:
    public:
        compile()
        {
        }
        /*******************************************************************************
         * 传入文件名file_name,以此名创建编译错误文件。
         *******************************************************************************/
        static bool Compile(std::string &file_name)
        {

            //  * 1.编译失败:创建compile_error后缀文件，将失败输出写进文件。
            //  * 2.编译成功:创建exe文件。


            // 拼接编译文件名字
            std::string src_file = PathUtil::AddSuffixSrc(file_name);
            // 拼接编译报错（compile_error）文件
            std::string com_err_file = PathUtil::AddSuffixComErr(file_name);

            // LOG(DEBUG) << "编译报错文件名：" << com_err_file << std::endl;
            // LOG(DEBUG) << "文件名：" << file_name << std::endl;
            // LOG(DEBUG) << "编译文件名：" << src_file << std::endl;

            // 重定向，将错误流输出的内容输出到收集错误的文件。
            umask(0);
            int fd_err = open(com_err_file.c_str(), O_CREAT | O_WRONLY, 0755);
            if (fd_err < 0)
            {
                LOG(ERROR) << "编译错误文件创建失败" << std::endl;
                return false;
            }

            pid_t pid = fork();
            if (pid < 0)
            {
                // 出错
                LOG(ERROR) << "编译子进程创建失败" << std::endl;
                close(fd_err);
                return false;
            }
            // 子进程
            else if (pid == 0)
            {
                dup2(fd_err,2);
                if (execlp("g++", "g++", "-o", file_name.c_str(), src_file.c_str(), "-std=c++11", "-D","COMPILER_ONLINE",nullptr) < 0)
                {
                    // 出错
                    LOG(ERROR) << "编译子进程程序替换失败" << std::endl;
                }
                exit(1);
            }
            // 父进程
            else
            {
                close(fd_err);
                int status;
                if (waitpid(pid, &status, 0) < 0)
                {
                    // 出错
                    LOG(ERROR) << "waitpid error" << std::endl;
                    return false;
                }
            }

            struct stat buff;
            if (stat(file_name.c_str(), &buff) < 0)
            {
                // 文件不存在
                LOG(ERROR) << "可执行文件不存在，编译失败" << "\n";
                return false;
            }
            LOG(INFO) << file_name << "程序编译完成" << std::endl;
            return true;
        }

        ~compile()
        {
        }
    };
}